/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef OHOS_AVMETA_DATA_H
#define OHOS_AVMETA_DATA_H

/**
 * @addtogroup avsession
 * @{
 *
 * @brief 音视频媒体会话，提供系统内媒体的统一控制能力。
 *
 * 功能包括媒体会话，媒体会话管理，媒体会话控制。
 *
 * @syscap SystemCapability.Multimedia.AVSession.Core
 * @since 9
 * @version 1.0
 */

/**
 * @file avmeta_data.h
 *
 * @brief 会话元数据设置、获取、拷贝等接口声明。
 *
 * @since 9
 * @version 1.0
 */

#include <bitset>
#include <memory>
#include <string>
#include <map>
#include "parcel.h"
#include "avsession_pixel_map.h"

#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) and !defined(IOS_PLATFORM)
#include <malloc.h>
#endif

namespace OHOS::AVSession {
/**
 * @brief 会话元数据类，提供获取metadata进程间传递的序列化和反序列话及数据拷贝的接口方法。
 */
class AVMetaData : public Parcelable {
public:

    /**
     * @brief 持续时间全局变量宏定义。
     *
     * @since 9
     * @version 1.0
     */
    static constexpr std::int64_t DURATION_ALWAYS_PLAY = -1;

    /**
     * @brief 会话元数据具体枚举项。
     */
    enum {
        /** 曲目ID */
        META_KEY_ASSET_ID = 0,
        /** 标题 */
        META_KEY_TITLE = 1,
        /** 艺术家 */
        META_KEY_ARTIST = 2,
        /** 制作人 */
        META_KEY_AUTHOR = 3,
        /** 专辑 */
        META_KEY_ALBUM = 4,
        /** 作词 */
        META_KEY_WRITER = 5,
        /** 作曲 */
        META_KEY_COMPOSER = 6,
        /** 媒体时长 */
        META_KEY_DURATION = 7,
        /** 媒体影像 */
        META_KEY_MEDIA_IMAGE = 8,
        /** 媒体影像路径 */
        META_KEY_MEDIA_IMAGE_URI = 9,
        /** 曲目发布日期 */
        META_KEY_PUBLISH_DATE = 10,
        /** 子标题 */
        META_KEY_SUBTITLE = 11,
        /** 曲目描述 */
        META_KEY_DESCRIPTION = 12,
        /** 歌词 */
        META_KEY_LYRIC = 13,
        /** 上一曲 */
        META_KEY_PREVIOUS_ASSET_ID = 14,
        /** 下一曲 */
        META_KEY_NEXT_ASSET_ID = 15,
        /** 无效指令，内部用来判断会话元数据是否有效 */
        META_KEY_MAX = 16
    };

    /**
     * @brief 引入掩码标记需要拷贝的会话元数据。
     *
     * @since 9
     * @version 1.0
     */
    using MetaMaskType = std::bitset<META_KEY_MAX>;

    /**
     * @brief 会话元数据默认构造函数。
     * @since 9
     * @version 1.0
     */
    AVMetaData() = default;

    /**
     * @brief 会话元数据默认析构函数。
     * @since 9
     * @version 1.0
     */
    ~AVMetaData() override
    {
#if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM) and !defined(IOS_PLATFORM)
#if defined(__BIONIC__)
        mallopt(M_PURGE, 0);
#endif
#endif
    }

    /**
     * @brief 实现会话元数据进程间传递的反序列化。
     *
     * @param data 序列化对象{@link Parcel}。
     * @return 如果反序列化成功，返回AVMetaData类型指针；失败则返回nullptr。
     * @see Marshalling
     * @since 9
     * @version 1.0
     */
    static AVMetaData *Unmarshalling(Parcel& data);

    /**
     * @brief 实现会话元数据进程间传递的序列化。
     *
     * @param data 保存序列化值的对象{@link Parcel}。
     * @return 如果序列化成功，则返回true；如果操作失败，则返回false。
     * @see Unmarshalling
     * @since 9
     * @version 1.0
     */
    bool Marshalling(Parcel& data) const override;

    /**
     * @brief 设置曲目ID。
     *
     * @param assetId 曲目ID,不可为空。
     * @see GetAssetId
     * @since 9
     * @version 1.0
     */
    void SetAssetId(const std::string& assetId);

    /**
     * @brief 获取曲目ID。
     *
     * @return 返回曲目ID。
     * @see SetAssetId
     * @since 9
     * @version 1.0
     */
    std::string GetAssetId() const;

    /**
     * @brief 设置标题。
     *
     * @param title 标题。
     * @see GetTitle
     * @since 9
     * @version 1.0
     */
    void SetTitle(const std::string& title);

    /**
     * @brief 获取标题。
     *
     * @return 返回标题。
     * @see SetTitle
     * @since 9
     * @version 1.0
     */
    std::string GetTitle() const;

    /**
     * @brief 设置艺术家名称。
     *
     * @param artist 艺术家名称。
     * @see GetArtist
     * @since 9
     * @version 1.0
     */
    void SetArtist(const std::string& artist);

    /**
     * @brief 获取艺术家名称。
     *
     * @return 返回艺术家名称。
     * @see SetArtist
     * @since 9
     * @version 1.0
     */
    std::string GetArtist() const;

    /**
     * @brief 设置制作人名称。
     *
     * @param author 制作人名称。
     * @see GetArtist
     * @since 9
     * @version 1.0
     */
    void SetAuthor(const std::string& author);

    /**
     * @brief 获取制作人名称。
     *
     * @return 返回制作人名称。
     * @see SetAuthor
     * @since 9
     * @version 1.0
     */
    std::string GetAuthor() const;

    /**
     * @brief 设置专辑名称。
     *
     * @param album 专辑名称。
     * @see GetAlbum
     * @since 9
     * @version 1.0
     */
    void SetAlbum(const std::string& album);

    /**
     * @brief 获取专辑名称。
     *
     * @return 返回专辑名称。
     * @see SetAlbum
     * @since 9
     * @version 1.0
     */
    std::string GetAlbum() const;

    /**
     * @brief 设置作词名称。
     *
     * @param writer 作词名称。
     * @see GetWriter
     * @since 9
     * @version 1.0
     */
    void SetWriter(const std::string& writer);

    /**
     * @brief 获取作词名称。
     *
     * @return 返回作词名称。
     * @see SetWriter
     * @since 9
     * @version 1.0
     */
    std::string GetWriter() const;

    /**
     * @brief 设置作曲名称。
     *
     * @param composer 作曲名称。
     * @see GetComposer
     * @since 9
     * @version 1.0
     */
    void SetComposer(const std::string& composer);

    /**
     * @brief 获取作曲名称。
     *
     * @return 返回作曲名称。
     * @see SetComposer
     * @since 9
     * @version 1.0
     */
    std::string GetComposer() const;

    /**
     * @brief 设置媒体时长。
     *
     * @param duration 媒体时长，必须大于等于-1，单位为ms 。
     * @see GetDuration
     * @since 9
     * @version 1.0
     */
    void SetDuration(int64_t duration);

    /**
     * @brief 获取媒体时长。
     *
     * @return 返回媒体时长，单位为ms。
     * @see SetDuration
     * @since 9
     * @version 1.0
     */
    int64_t GetDuration() const;

    /**
     * @brief 设置媒体图片。
     *
     * @param mediaImage 媒体图片{@link AVSessionPixelMap}。
     * @see GetMediaImage
     * @since 9
     * @version 1.0
     */
    void SetMediaImage(const std::shared_ptr<AVSessionPixelMap>& mediaImage);

    /**
     * @brief 获取媒体图片。
     *
     * @return 返回媒体图片{@link AVSessionPixelMap}。
     * @see SetMediaImage
     * @since 9
     * @version 1.0
     */
    std::shared_ptr<AVSessionPixelMap> GetMediaImage() const;

    /**
     * @brief 设置媒体图片URI。
     *
     * @param mediaImageUri 媒体图片URI。
     * @see GetMediaImageUri
     * @since 9
     * @version 1.0
     */
    void SetMediaImageUri(const std::string& mediaImageUri);

    /**
     * @brief 获取媒体图片URI。
     *
     * @return 返回媒体图片URI。
     * @see SetMediaImageUri
     * @since 9
     * @version 1.0
     */
    std::string GetMediaImageUri() const;

    /**
     * @brief 设置曲目发布日期，时间戳，单位为ms。
     *
     * @param date 曲目发布日期，时间戳，单位为ms。
     * @see GetPublishDate
     * @since 9
     * @version 1.0
     */
    void SetPublishDate(double date);

    /**
     * @brief 获取曲目发布日期，时间戳，单位为ms。
     *
     * @return 返回曲目发布日期，时间戳，单位为ms。
     * @see SetPublishDate
     * @since 9
     * @version 1.0
     */
    double GetPublishDate() const;

    /**
     * @brief 设置子标题。
     *
     * @param subTitle 子标题。
     * @see GetSubTitle
     * @since 9
     * @version 1.0
     */
    void SetSubTitle(const std::string& subTitle);

    /**
     * @brief 获取子标题。
     *
     * @return 返回子标题。
     * @see SetSubTitle
     * @since 9
     * @version 1.0
     */
    std::string GetSubTitle() const;

    /**
     * @brief 设置曲目描述。
     *
     * @param description 曲目描述。
     * @see GetDescription
     * @since 9
     * @version 1.0
     */
    void SetDescription(const std::string& description);

    /**
     * @brief 获取曲目描述。
     *
     * @return 返回曲目描述。
     * @see SetDescription
     * @since 9
     * @version 1.0
     */
    std::string GetDescription() const;

    /**
     * @brief 设置歌词。
     *
     * @param lyric 歌词。
     * @see GetLyric
     * @since 9
     * @version 1.0
     */
    void SetLyric(const std::string& lyric);

    /**
     * @brief 获取歌词。
     *
     * @return 返回歌词。
     * @see SetLyric
     * @since 9
     * @version 1.0
     */
    std::string GetLyric() const;

    /**
     * @brief 设置上一曲曲目ID。
     *
     * @param assetId 上一曲曲目ID。
     * @see GetPreviousAssetId
     * @since 9
     * @version 1.0
     */
    void SetPreviousAssetId(const std::string& assetId);

    /**
     * @brief 获取上一曲曲目ID。
     *
     * @return 返回上一曲曲目ID。
     * @see SetPreviousAssetId
     * @since 9
     * @version 1.0
     */
    std::string GetPreviousAssetId() const;

    /**
     * @brief 设置下一曲曲目ID。
     *
     * @param assetId 下一曲曲目ID。
     * @see GetNextAssetId
     * @since 9
     * @version 1.0
     */
    void SetNextAssetId(const std::string& assetId);

    /**
     * @brief 获取下一曲曲目ID。
     *
     * @return 返回下一曲曲目ID。
     * @see SetNextAssetId
     * @since 9
     * @version 1.0
     */
    std::string GetNextAssetId() const;

    /**
     * @brief 重置所有会话元数据项。
     *
     * @since 9
     * @version 1.0
     */
    void Reset();

    /**
     * @brief 获取掩码。
     *
     * @return 返回掩码{@link MetaMaskType}。
     * @since 9
     * @version 1.0
     */
    MetaMaskType GetMetaMask() const;

    /**
     * @brief 根据metadata掩码,将metadata项复制到metaOut。
     *
     * @param mask metadata掩码{@link MetaMaskType}。
     * @param metaOut metadata已拷贝成功的出参{@link AVMetaData}。
     * @return 成功返回true；失败则返回false。
     * @since 9
     * @version 1.0
     */
    bool CopyToByMask(MetaMaskType& mask, AVMetaData& metaOut) const;

    /**
     * @brief 根据metaIn元掩码的设置位从metaIn复制metadata项。
     *
     * @param metaIn：会话元数据将要拷贝的入参{@link AVMetaData}。
     * @return 成功返回true；失败则返回false。
     * @since 9
     * @version 1.0
     */
    bool CopyFrom(const AVMetaData& metaIn);

    /**
     * @brief 会话元数据有效性判断。
     *
     * @return 有效返回true；无效则返回false。
     * @since 9
     * @version 1.0
     */
    bool IsValid() const;
    
    /**
     * @brief 会话元数据数组，用于分布式业务，设置会话属性。
     *
     * @since 9
     * @version 1.0
     */
    const static inline std::vector<int32_t> localCapability {
        META_KEY_ASSET_ID,
        META_KEY_TITLE,
        META_KEY_ARTIST,
        META_KEY_AUTHOR,
        META_KEY_ALBUM,
        META_KEY_WRITER,
        META_KEY_COMPOSER,
        META_KEY_DURATION,
        META_KEY_MEDIA_IMAGE,
        META_KEY_MEDIA_IMAGE_URI,
        META_KEY_PUBLISH_DATE,
        META_KEY_SUBTITLE,
        META_KEY_DESCRIPTION,
        META_KEY_LYRIC,
        META_KEY_PREVIOUS_ASSET_ID,
        META_KEY_NEXT_ASSET_ID,
    };

private:
    /** 用于记录会话元数据掩码{@link MetaMaskType} */
    MetaMaskType metaMask_;
    /** 曲目ID */
    std::string assetId_ = "";
    /** 标题 */
    std::string title_ = "";
    /** 艺术家 */
    std::string artist_ = "";
    /** 制作人 */
    std::string author_ = "";
    /** 专辑 */
    std::string album_ = "";
    /** 作词 */
    std::string writer_ = "";
    /** 作曲 */
    std::string composer_ = "";
    /** 媒体时长 */
    int64_t duration_ = 0;
    /** 媒体影像{@link AVSessionPixelMap} */
    std::shared_ptr<AVSessionPixelMap> mediaImage_ = nullptr;
    /** 媒体影像路径 */
    std::string mediaImageUri_ = "";
    /** 曲目发布日期，时间戳，单位为ms */
    double publishDate_ = 0;
    /** 子标题 */
    std::string subTitle_ = "";
    /** 曲目描述 */
    std::string description_ = "";
    /** 歌词 */
    std::string lyric_ = "";
    /** 上一曲 */
    std::string previousAssetId_ = "";
    /** 下一曲 */
    std::string nextAssetId_ = "";

    /**
     * @brief 将源会话元数据的曲目ID拷贝至目标元数据的曲目ID。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneAssetId(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的标题拷贝至目标会话元数据的标题。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneTitle(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的艺术家拷贝至目标会话元数据的艺术家。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneArtist(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的制作人拷贝至目标会话元数据的制作人。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneAuthor(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的专辑名称拷贝至目标会话元数据的专辑名称。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneAlbum(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的作词拷贝至目标会话元数据的作词。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneWriter(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的作曲人名称拷贝至目标会话元数据的作曲人名称。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneComposer(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的媒体时长拷贝至目标会话元数据的媒体时长。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneDuration(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的图片拷贝至目标会话元数据的图片。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneMediaImage(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的图片url拷贝至目标会话元数据的图片url。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneMediaImageUri(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的发布日期拷贝至目标会话元数据的发布日期。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void ClonePublishData(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的子标题拷贝至目标会话元数据的子标题。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneSubTitle(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的曲目描述拷贝至目标会话元数据的曲目描述。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneDescription(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的歌词拷贝至目标会话元数据的歌词。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @since 9
     * @version 1.0
     */
    static void CloneLyric(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的上一曲拷贝至目标元会话数据的上一曲。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @see CloneNextAssetId
     * @since 9
     * @version 1.0
     */
    static void ClonePreviousAssetId(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 将源会话元数据的下一曲拷贝至目标会话元数据的下一曲。
     *
     * @param from 源会话元数据{@link AVMetaData}。
     * @param to 目标会话元数据{@link AVMetaData}。
     * @see ClonePreviousAssetId
     * @since 9
     * @version 1.0
     */
    static void CloneNextAssetId(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 用于重定义会话元数据拷贝函数指针类型。
     *
     * @since 9
     * @version 1.0
     */
    using CloneActionType = void(*)(const AVMetaData& from, AVMetaData& to);

    /**
     * @brief 内联函数指针数组中根据具体索引进行对应会话元数据项操作。
     *
     * @since 9
     * @version 1.0
     */
    static inline CloneActionType cloneActions[META_KEY_MAX] = {
        [META_KEY_ASSET_ID] = &AVMetaData::CloneAssetId,
        [META_KEY_TITLE] = &AVMetaData::CloneTitle,
        [META_KEY_ARTIST] = &AVMetaData::CloneArtist,
        [META_KEY_AUTHOR] = &AVMetaData::CloneAuthor,
        [META_KEY_ALBUM] = &AVMetaData::CloneAlbum,
        [META_KEY_WRITER] = &AVMetaData::CloneWriter,
        [META_KEY_COMPOSER] = &AVMetaData::CloneComposer,
        [META_KEY_DURATION] = &AVMetaData::CloneDuration,
        [META_KEY_MEDIA_IMAGE] = &AVMetaData::CloneMediaImage,
        [META_KEY_MEDIA_IMAGE_URI] = &AVMetaData::CloneMediaImageUri,
        [META_KEY_PUBLISH_DATE] = &AVMetaData::ClonePublishData,
        [META_KEY_SUBTITLE] = &AVMetaData::CloneSubTitle,
        [META_KEY_DESCRIPTION] = &AVMetaData::CloneDescription,
        [META_KEY_LYRIC] = &AVMetaData::CloneLyric,
        [META_KEY_PREVIOUS_ASSET_ID] = &AVMetaData::ClonePreviousAssetId,
        [META_KEY_NEXT_ASSET_ID] = &AVMetaData::CloneNextAssetId,
    };
};
} // namespace OHOS::AVSession
/** @}*/
#endif // OHOS_AVMETA_DATA_H